<?php


namespace App\Foundation\Utils;


use app\common\service\Aes;

class Rsa
{


    function __construct(){
        $this->privatePath = BASE_PATH.'/private/';
    }

    //解密客户端aeskey
    function decode($data,$appId){
        $result['code'] = 200;
        $privateKeyStr = file_get_contents($this->privatePath.'server_private_key_'.$appId.'.pem');
        $private_key = openssl_pkey_get_private($privateKeyStr);
        openssl_private_decrypt(base64_decode($data), $decrypted, $private_key);
        return $decrypted;
    }

    //加密客户端aeskey
    public function encrypt($data = '',$appId)
    {
        $pubicKeyStr = file_get_contents($this->privatePath.'app_public_key_'.$appId.'.pem');
        $publicKey = openssl_pkey_get_public($pubicKeyStr);
        return openssl_public_encrypt($data,$encrypted,$publicKey) ? base64_encode($encrypted) : false;
    }

    //生成服务端签名
    function getSign($signString,$appId){
        $privateKeyStr = file_get_contents($this->privatePath.'server_private_key_'.$appId.'.pem');
        $private_key = openssl_pkey_get_private($privateKeyStr);
        openssl_sign($signString, $signature, $private_key,OPENSSL_ALGO_SHA256);
        openssl_free_key($private_key);
        return base64_encode($signature);
    }

    //校验app端签名
    function checkSign($data, $sign,$appId) {
        $publicKeyStr = file_get_contents($this->privatePath.'app_public_key_'.$appId.'.pem');
        $publicKey = openssl_pkey_get_public($publicKeyStr);
        $result = openssl_verify($data, base64_decode($sign), $publicKey,OPENSSL_ALGO_SHA256);
        openssl_free_key($publicKey);
        return $result;
    }

    //客户端传输参数解密
    public function getDecryptData($appId){
        $secretVerify = $this->secretVerify();
        if($secretVerify){

            $data = $this->request->post('data');
            $aesEncryptKey = $this->request->post('token');
            $rsa = new \app\common\service\Rsa();
            $aesKey = $rsa->decode($aesEncryptKey,$appId);
            if(!$aesKey){
                $this->returncode(300,'数据校验不通过');
            }

            $iv = $this->getDecryptIv($appId,$aesKey);

            $aes = new Aes($aesKey,$iv);
            $decryptData = $aes->decrypt($data);
            if(!$decryptData){
                $this->returncode(300,'数据校验不通过');
            }
            $sign = $decryptData['sign'];
            unset($decryptData['sign']);
            ksort($decryptData);
            $signArr = array_values($decryptData);

            $signStr = implode($signArr);
            if(!$rsa->checkSign($signStr,$sign,$appId)){
                $this->returncode(300,'签名校验失败');
            }
        }else{
            $decryptData = $this->request->param();
        }
        return $decryptData;
    }
}